<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Think\Db\Driver;

use Think\Db\Driver;

/**
 * mysql数据库驱动
 */
class Mysql extends Driver {
	
	/**
	 * 解析pdo连接的dsn信息
	 * 
	 * @access public
	 * @param array $config
	 *        	连接信息
	 * @return string
	 */
	protected function parseDsn($config) {
		$dsn = 'mysql:dbname=' . $config ['database'] . ';host=' . $config ['hostname'];
		if (! empty ( $config ['hostport'] )) {
			$dsn .= ';port=' . $config ['hostport'];
		} elseif (! empty ( $config ['socket'] )) {
			$dsn .= ';unix_socket=' . $config ['socket'];
		}
		
		if (! empty ( $config ['charset'] )) {
			if (version_compare ( PHP_VERSION, '5.3.6', '<' )) {
				// PHP5.3.6以下不支持charset设置
				$this->options [\PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . $config ['charset'];
			} else {
				$dsn .= ';charset=' . $config ['charset'];
			}
		}
		return $dsn;
	}
	
	/**
	 * 取得数据表的字段信息
	 * 
	 * @access public
	 */
	public function getFields($tableName) {
		$this->initConnect ( true );
		list ( $tableName ) = explode ( ' ', $tableName );
		$sql = 'SHOW COLUMNS FROM `' . $tableName . '`';
		$result = $this->query ( $sql );
		$info = array ();
		if ($result) {
			foreach ( $result as $key => $val ) {
				$info [$val ['field']] = array (
						'name' => $val ['field'],
						'type' => $val ['type'],
						'notnull' => ( bool ) ($val ['null'] === ''), // not null is empty, null is yes
						'default' => $val ['default'],
						'primary' => (strtolower ( $val ['key'] ) == 'pri'),
						'autoinc' => (strtolower ( $val ['extra'] ) == 'auto_increment') 
				);
			}
		}
		return $info;
	}
	
	/**
	 * 取得数据库的表信息
	 * 
	 * @access public
	 */
	public function getTables($dbName = '') {
		$sql = ! empty ( $dbName ) ? 'SHOW TABLES FROM ' . $dbName : 'SHOW TABLES ';
		$result = $this->query ( $sql );
		$info = array ();
		foreach ( $result as $key => $val ) {
			$info [$key] = current ( $val );
		}
		return $info;
	}
	
	/**
	 * 字段和表名处理
	 * 
	 * @access protected
	 * @param string $key        	
	 * @return string
	 */
	protected function parseKey(&$key) {
		$key = trim ( $key );
		if (! is_numeric ( $key ) && ! preg_match ( '/[,\'\"\*\(\)`.\s]/', $key )) {
			$key = '`' . $key . '`';
		}
		return $key;
	}
	
	/**
	 * 批量插入记录
	 * 
	 * @access public
	 * @param mixed $dataSet
	 *        	数据集
	 * @param array $options
	 *        	参数表达式
	 * @param boolean $replace
	 *        	是否replace
	 * @return false | integer
	 */
	public function insertAll($dataSet, $options = array(), $replace = false) {
		$values = array ();
		$this->model = $options ['model'];
		if (! is_array ( $dataSet [0] ))
			return false;
		$this->parseBind ( ! empty ( $options ['bind'] ) ? $options ['bind'] : array () );
		$fields = array_map ( array (
				$this,
				'parseKey' 
		), array_keys ( $dataSet [0] ) );
		foreach ( $dataSet as $data ) {
			$value = array ();
			foreach ( $data as $key => $val ) {
				if (is_array ( $val ) && 'exp' == $val [0]) {
					$value [] = $val [1];
				} elseif (is_scalar ( $val )) {
					if (0 === strpos ( $val, ':' ) && in_array ( $val, array_keys ( $this->bind ) )) {
						$value [] = $this->parseValue ( $val );
					} else {
						$name = count ( $this->bind );
						$value [] = ':' . $name;
						$this->bindParam ( $name, $val );
					}
				}
			}
			$values [] = '(' . implode ( ',', $value ) . ')';
		}
		$sql = ($replace ? 'REPLACE' : 'INSERT') . ' INTO ' . $this->parseTable ( $options ['table'] ) . ' (' . implode ( ',', $fields ) . ') VALUES ' . implode ( ',', $values );
		$sql .= $this->parseComment ( ! empty ( $options ['comment'] ) ? $options ['comment'] : '' );
		return $this->execute ( $sql, ! empty ( $options ['fetch_sql'] ) ? true : false );
	}
}
